package com.geek.framework.study.config.microprofile.source;

import com.geek.framework.study.config.microprofile.enums.ConfigSourceEnum;
import org.eclipse.microprofile.config.spi.ConfigSource;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

import static java.util.Collections.sort;



public class DefaultResourceConfigSources implements ConfigSource {

    private static final String CONFIG_LOCATION = "META-INF/microprofile-config.properties";

    private static final String CONFIG_ORDINAL_PROPERTY_NAME = "config_ordinal";

    private final List<ConfigSource> configSourceList = new LinkedList<>();

    public DefaultResourceConfigSources() {
        init();
    }

    protected void init() {
        ClassLoader classLoader = getClass().getClassLoader();
        try {
            Enumeration<URL> resources = classLoader.getResources(CONFIG_LOCATION);
            while (resources.hasMoreElements()) {
                URL url = resources.nextElement();
                if (url == null) {
                    return;
                }
                try (InputStream inputStream = url.openStream()) {
                    Properties properties = new Properties();
                    properties.load(inputStream);

                    Map<String, String> stringMap = new HashMap<>();
                    properties.forEach((k,v)->{
                        stringMap.put(String.valueOf(k), String.valueOf(v));
                    });

                    Integer ordinal = Optional.ofNullable(properties.getProperty(CONFIG_ORDINAL_PROPERTY_NAME))
                            .map(Integer::valueOf)
                            .orElse(100);
                    SimpleConfigSource simpleConfigSource = new SimpleConfigSource(url.toString(), ordinal, stringMap);
                    configSourceList.add(simpleConfigSource);
                } catch (Exception e) {
                    //todo
                }
            }
            sort(configSourceList, Comparator.comparingInt(ConfigSource::getOrdinal));

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Set<String> getPropertyNames() {
        Set<String> propertyNames = new LinkedHashSet<>();
        for (ConfigSource configSource : configSourceList) {
            Set<String> propertyNameSet = configSource.getPropertyNames();
            for (String propertyName : propertyNameSet) {
                if (!propertyNames.contains(propertyName)) {
                    propertyNames.add(propertyName);
                }
            }
        }
        return Collections.unmodifiableSet(propertyNames);
    }

    @Override
    public String getValue(String s) {
        for (ConfigSource configSource : configSourceList) {
            String value = configSource.getValue(s);
            if (value != null) {
                return value;
            }
        }
        return null;
    }

    @Override
    public String getName() {
        return ConfigSourceEnum.MICRO_PROFILE_DEFAULT_CONFIG.getName();
    }

    @Override
    public int getOrdinal() {
        return ConfigSourceEnum.MICRO_PROFILE_DEFAULT_CONFIG.getOrdinal();
    }

}
